fun main(args: Array<String>) {

    /**
     * 在kotlin 中任何表达式都可以用标签（label）来标记。标签的格式为标识符后跟@符号，例如：abc@、fooBar@、bpg@都是有效的标签。
     * 要为一个表达式加标签，我们只要在其前加标签即可
     */
    loop@ for (i in 1..100) {
        //...
        print(i)
    }
    println()
    //现在我们可以用标签限制break或者continue：
    for (i in 1..100) {
        for (j in 1..100) {
            if (i >= 2) break
            print(j)
        }
    }

    //标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代。
    bpg@ for (i in 1..3) { //bpg@可以随意定义，loop@可以，其他的也可以
        println("i = " + i)
        for (j in 1..3) {
            if (i == 2) break@bpg //这样可以直接break到外层for循环，如果不加@loop,则是break出内层循环。
            println("j = " + j)
        }
        println()
    }

    /**
     * 标签处返回
     * kotlin 有函数字面量、局部函数和对象表达式，因此kotlin的函数可以被嵌套。标签限制的return允许我们从外层函数返回。
     * 最终要的一个用途就是lambda表达式中返回，回想一下我们这么写的时候
     */
    var ints = intArrayOf(2, 3, 6, 0, 1)
//    ints.forEach {
//        if (it == 0) return
//        print(it)
//    }

    //这个return表达式从最直接包围它的函数即foo中返回。（注意，这种非局部的返回只支持传给内联函数的lambda表达式。）如果我们需要
    //从lambda表达式中返回，我们必须给它加标签并用以限制return
//    ints.forEach lit@{
//        if (it == 0) return@lit
//        println(it)
//    }

    //现在，它只会从lambda表达式中返回，通常情况下使用隐式标签更方便。该标签与接受该lambda的函数同名
//    ints.forEach {
//        if (it == 0) return@forEach //ints.forEach之后不定义标签，后面必须与接受该lambda的函数同名，
//        print(it)
//    }

    //或者，我们用一个匿名函数代替lambda表达式。匿名函数内部的return语句将从该匿名函数自身返回
    ints.forEach(fun(value: Int) {
        if (value == 0) return
        print(value)
    })

    //当要返一个回值的时候，解析器优先选用标签限制的 return，即  return@a 1
    //意为“从标签 @a 返回 1”，而不是“返回一个标签标注的表达式 (@a 1) ”。


}